package com.easylinkin.linkappapi.lobar.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.config.entity.Config;
import com.easylinkin.linkappapi.config.service.ConfigService;
import com.easylinkin.linkappapi.lobar.dto.*;
import com.easylinkin.linkappapi.lobar.dto.app.AppUserGateDTO;
import com.easylinkin.linkappapi.lobar.dto.app.EnterpriseDTO;
import com.easylinkin.linkappapi.lobar.dto.app.EpidemicDTO;
import com.easylinkin.linkappapi.lobar.dto.app.LobarUserDTO;
import com.easylinkin.linkappapi.lobar.dto.screen.HourAnalysisDTO;
import com.easylinkin.linkappapi.lobar.dto.screen.LobarScreenDTO;
import com.easylinkin.linkappapi.lobar.dto.screen.WarningDTO;
import com.easylinkin.linkappapi.lobar.entity.*;
import com.easylinkin.linkappapi.lobar.mapper.*;
import com.easylinkin.linkappapi.lobar.service.LaborCompanyService;
import com.easylinkin.linkappapi.lobar.service.LobarScreenService;
import com.easylinkin.linkappapi.lobar.service.LobarSetService;
import com.easylinkin.linkappapi.lobar.service.UserClockService;
import com.easylinkin.linkappapi.lobar.util.LobarUtils;
import com.easylinkin.linkappapi.lobar.util.PercentageUtils;
import com.easylinkin.linkappapi.lobar.vo.LobarScreenWarnVo;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.tenant.dto.LinkappTenantDTO;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Author: kan yuanfeng
 * @Date: 2022/4/27 15:10
 * @Description:
 */
@Service
public class LobarScreenServiceImpl implements LobarScreenService {

  @Autowired
  private UserProjectMapper userProjectMapper;
  @Resource
  private LinkappUserContextProducer linkappUserContextProducer;
  @Autowired
  private LaborCompanyProjectMapper laborCompanyProjectMapper;
  @Autowired
  private UserClockMapper userClockMapper;
  @Autowired
  private UserStatisticsMapper userStatisticsMapper;
  @Autowired
  private UserWarningMapper userWarningMapper;
  @Autowired
  private GroupWarningMapper groupWarningMapper;
  @Autowired
  private AgeWarningMapper ageWarningMapper;
  @Autowired
  private CertificateWarningMapper certificateWarningMapper;
  @Autowired
  private UserRecordMapper userRecordMapper;
  @Autowired
  private UserClockService userClockService;
  @Autowired
  private ConfigService configService;
  @Autowired
  private LaborCompanyService laborCompanyService;
  @Autowired
  private GroupMapper groupMapper;
  @Autowired
  private LinkappTenantMapper linkappTenantMapper;
  @Autowired
  private EpidemicWarningMapper epidemicWarningMapper;
  @Autowired
  private LaborCompanyMapper laborCompanyMapper;
  @Autowired
  private UserGateMapper userGateMapper;
  @Autowired
  private LobarSetService lobarSetService;

  @Resource
  private UserOutinWarningMapper userOutinWarningMapper;

  /**
   * @Description: 人员分析(劳务公司,在场人数,劳务工种)
   * type有值表示需要过滤，取分包单位数据(还要根据配置)
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @Override
  public Map<String, Integer> countAnalysis(Integer type) {
    Map<String, Integer> map = new HashMap<>();
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //统计参建单位
    QueryWrapper<LaborCompanyProject> companyWrapper = new QueryWrapper<>();
    companyWrapper.eq("tenant_id_",tenantId)
        .eq("status_",1);
    JSONArray buildTypeArray = new JSONArray();
    if (type != null && isFilter(tenantId)){
      Config typeConfig = configService
          .getOneByKey("LABOUR_BIG_SCREEN_LABOUR_COMPANY_TYPE");
      if(typeConfig!=null){
        String value = typeConfig.getValue();
        if(StringUtils.isNotBlank(value)){
          buildTypeArray = JSONUtil.parseArray(value);
          //过滤掉非专业单位和分包单位的
          QueryWrapper<LaborCompany> laborCompanyQueryWrapper = new QueryWrapper<>();
          laborCompanyQueryWrapper.in("build_type_",buildTypeArray);
          List<LaborCompany> list = laborCompanyService.list(laborCompanyQueryWrapper);
          if(CollectionUtil.isNotEmpty(list)){
            List<String> companyIds = list.stream().map(item -> item.getId())
                .collect(Collectors.toList());
            companyWrapper.in("company_id_",companyIds);
          }
        }
      }
    }
    Integer integer = laborCompanyProjectMapper.selectCount(companyWrapper);
    map.put("laborCompany",integer);
    //在场人数
    QueryWrapper<UserProject> userWrapper = new QueryWrapper<>();
    userWrapper.eq("tenant_id_",tenantId)
        .eq("status_",1);
    //过滤掉对应的人员
    if(CollectionUtil.isNotEmpty(buildTypeArray)){
      List<UserProjectDTO> userProjectDTOS = userProjectMapper.findByTenantId(tenantId);
      List<String> buildTypeList = buildTypeArray.toList(String.class);
      userProjectDTOS.removeIf(u-> !buildTypeList.contains(u.getBuildType()));
      List<String> userIds = userProjectDTOS.stream().map(item -> item.getUserId())
          .collect(Collectors.toList());
      userWrapper.in("user_id_",userIds);
    }
    List<UserProject> userProjects = userProjectMapper.selectList(userWrapper);
    map.put("user",userProjects.size());
    //管理员
    map.put("manage",userProjects.stream().filter(u -> LobarUtils.isManager(u.getWorkType())).collect(Collectors.toList()).size());
    //工种
    Set<String> set = userProjects.stream()
        .filter(u -> StringUtils.isNotBlank(u.getWorkType()) && u.getWorkType().endsWith("其他"))
        .map(UserProject::getWorkType).collect(Collectors.toSet());
    Set<String> workTypes = userProjects.stream().filter(u -> StringUtils.isNotBlank(u.getWorkType()))
        .map(u -> u.getWorkType()).collect(Collectors.toSet());
    if (set.size() > 1){
      map.put("workType",workTypes.size()-1);
    }else {
      map.put("workType",workTypes.size());
    }
    return map;
  }

  /**
   * @Description: 人员统计
   * type有值表示需要过滤，取分包单位数据
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @Override
  public Map<String, List<LobarScreenDTO>> countUser(Integer type) {
    Map<String, List<LobarScreenDTO>> map = new HashMap<>();
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    List<String> buildTypes = new ArrayList<>();
    if (null != type && isFilter(tenantId)){
      Config typeConfig = configService
          .getOneByKey("LABOUR_BIG_SCREEN_LABOUR_COMPANY_TYPE");
      if(typeConfig!=null){
        String value = typeConfig.getValue();
        if(StringUtils.isNotBlank(value)){
          JSONArray jsonArray = JSONUtil.parseArray(value);
          buildTypes = jsonArray.toList(String.class);
        }
      }
    }
    //在场人数
    List<UserProjectDTO> userProjects = userProjectMapper.countUser(tenantId,buildTypes);
    //参建单位
    List<LaborCompanyProjectDTO> laborCompanyProjectDTOS = laborCompanyProjectMapper.findAll(tenantId);
    if(CollectionUtil.isNotEmpty(buildTypes)){
      List<String> buildTypeList = new ArrayList<>(buildTypes);
      laborCompanyProjectDTOS.removeIf(item->!buildTypeList.contains(item.getBuildType()));
    }
    Map<String, List<UserProjectDTO>> companyMap = userProjects.stream()
            .filter(c->StringUtils.isNotBlank(c.getCompanyName()))
        .collect(Collectors.groupingBy(c -> c.getCompanyName()));
    List<LobarScreenDTO> laborCompanys = new ArrayList<>();
    List<LobarScreenDTO> finalLaborCompanys = laborCompanys;
    laborCompanyProjectDTOS.forEach(l ->{
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO(l.getName(),0,l.getAbbreviation());
      List<UserProjectDTO> userProjectDTOS = companyMap.get(l.getName());
      if (null != userProjectDTOS && userProjectDTOS.size()>0){
        lobarScreenDTO.setNum(userProjectDTOS.size());
      }
      finalLaborCompanys.add(lobarScreenDTO);
    });
    laborCompanys = laborCompanys.stream().sorted(Comparator.comparing(LobarScreenDTO::getNum)).collect(Collectors.toList());
    map.put("laborCompany",laborCompanys);

    //管理员
    Map<String, List<UserProjectDTO>> manageMap = userProjects.stream()
            .filter(u->LobarUtils.isManager(u.getWorkType()))
            .collect(Collectors.groupingBy(u -> u.getWorkType().substring(u.getWorkType().lastIndexOf("/")+1)));
    List<LobarScreenDTO> manageWorks = new ArrayList<>();
    manageMap.forEach((k,v) ->{
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO(k,v.size());
      manageWorks.add(lobarScreenDTO);
    });
    map.put("manage",manageWorks.stream().sorted(Comparator.comparing(LobarScreenDTO::getNum).reversed()).collect(
            Collectors.toList()));

    //工种
    Map<String, List<UserProjectDTO>> workMap = userProjects.stream()
        .filter(u-> StringUtils.isNotBlank(u.getWorkType()))
        .collect(Collectors.groupingBy(u -> u.getWorkType().substring(u.getWorkType().lastIndexOf("/")+1)));
    List<LobarScreenDTO> works = new ArrayList<>();
    workMap.forEach((k,v) ->{
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO(k,v.size());
      works.add(lobarScreenDTO);
    });
    map.put("workType",works.stream().sorted(Comparator.comparing(LobarScreenDTO::getNum).reversed()).collect(
        Collectors.toList()));

    //年龄
    List<LobarScreenDTO> ages = listGroupByAgePeriod(userProjects);

//    List<UserProjectDTO> dtos6 = userProjects.stream()
//        .filter(u ->DateUtil.age(u.getBirthday(), new Date()) >= 60)
//        .collect(Collectors.toList());
//    LobarScreenDTO lobarScreenDTO6 = new LobarScreenDTO("60岁-65岁",dtos6.size());
//    ages.add(lobarScreenDTO6);
    map.put("age",ages);
    //籍贯
    Map<String, List<UserProjectDTO>> nativeMap = userProjects.stream()
        .filter(u->StringUtils.isNotBlank(u.getCard()))
        .collect(Collectors.groupingBy(c -> getNative(c.getCard())));
    List<LobarScreenDTO> natives = new ArrayList<>();
    nativeMap.forEach((k,v) ->{
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO(k,v.size());
      natives.add(lobarScreenDTO);
    });
    List<LobarScreenDTO> dtoList = natives.stream()
        .sorted(Comparator.comparing(LobarScreenDTO::getNum).reversed())
        .collect(Collectors.toList());
    map.put("native",dtoList);
    return map;
  }

  /**
   * 当前出场人数时间图
   * type有值表示需要过滤，取分包单位数据
   * @param userWorkType 人员类型 1:作业人员 2:管理人员
   */
  @Override
  public List<LobarScreenDTO> userByTime(Integer type,Integer userWorkType) {
    UserClockDTO userClockDTO = new UserClockDTO();
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    userClockDTO.setTenantId(tenantId);
    userClockDTO.setStartTime(DateUtil.beginOfDay(new Date()));
    userClockDTO.setEndTime(DateUtil.endOfDay(new Date()));
    List<LobarScreenDTO> rerult = new ArrayList<>();
    //过滤掉不符合类型的参建单位的人员
    List<UserProjectDTO> userProjectDTOS = userProjectMapper.findByTenantId(
        tenantId);

    //增加人员类型的过滤
    Boolean filter = isFilter(tenantId);
    if ((null != type && filter) || userWorkType!= null){
      if (null != type && filter){
        Config typeConfig = configService
                .getOneByKey("LABOUR_BIG_SCREEN_LABOUR_COMPANY_TYPE");
        if(typeConfig!=null){
          String value = typeConfig.getValue();
          if(StringUtils.isNotBlank(value)){
            JSONArray jsonArray = JSONUtil.parseArray(value);
            //过滤掉非专业单位和分包单位的
            userProjectDTOS.removeIf(u-> !jsonArray.contains(u.getBuildType()));
          }
        }
      }
      //工种
      if (Integer.valueOf(1).equals(userWorkType)){
        userProjectDTOS.removeIf(u-> LobarUtils.isManager(u.getWorkType()));
      }else if (Integer.valueOf(2).equals(userWorkType)){
        userProjectDTOS.removeIf(u-> !LobarUtils.isManager(u.getWorkType()));
      }
      List<String> userIds = userProjectDTOS.stream().map(UserProject::getUserId).filter(StringUtils::isNotBlank)
              .collect(Collectors.toList());
      userClockDTO.setUserIds(userIds);
    }
//    List<LobarScreenDTO> lobarScreenDTOS1 = userClockMapper.userByTime(userClockDTO);
    List<UserClock> userClocks = userClockMapper.findUserByTime(userClockDTO);
    for (int i = 0; i < 24; i++) {
      Calendar calendar = DateUtil.beginOfDay(Calendar.getInstance());
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO();
      calendar.add(Calendar.HOUR_OF_DAY,i);
      List<UserClock> clocks = userClocks.stream()
//              两个时间是同一个小时的
              .filter(l -> null != l.getClockTime()
                      && DateUtil.hour(l.getClockTime(),true) == DateUtil.hour(calendar.getTime(),true))
              .collect(Collectors.toList());
      if (CollectionUtil.isNotEmpty(clocks)){
        Set<String> userIds = clocks.stream().map(UserClock::getUserId)
                .filter(StringUtils::isNotBlank).collect(Collectors.toSet());
        lobarScreenDTO.setNum(userIds.size());
        if (CollectionUtil.isNotEmpty(userIds)){
          //保存userIds
          lobarScreenDTO.setUserIds(new ArrayList<>(userIds));
        }
      }else {
        lobarScreenDTO.setNum(0);
      }
      lobarScreenDTO.setCTime(calendar.getTime());
      rerult.add(lobarScreenDTO);
    }
    rerult = rerult.stream().sorted(Comparator.comparing(LobarScreenDTO::getCTime)).collect(Collectors.toList());
    return rerult;
  }

  /**
   * 各参建单位出勤率
   * type有值表示需要过滤，取分包单位数据
   */
  @Override
  public List<LobarScreenDTO> attendance(Integer type,Integer userWorkType) {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //查询在场的参建单位
    List<LaborCompanyProjectDTO> laborCompanyProjectDTOS = laborCompanyProjectMapper.findAll(tenantId);
    if (null != type  && isFilter(tenantId)){
      Config typeConfig = configService
          .getOneByKey("LABOUR_BIG_SCREEN_LABOUR_COMPANY_TYPE");
      if(typeConfig!=null){
        String value = typeConfig.getValue();
        if(StringUtils.isNotBlank(value)){
          JSONArray jsonArray = JSONUtil.parseArray(value);
          //过滤掉非专业单位和分包单位的
          laborCompanyProjectDTOS.removeIf(u-> !jsonArray.contains(u.getBuildType()));
        }
      }
    }
    UserStatisticsDTO userStatisticsDTO = new UserStatisticsDTO();
    userStatisticsDTO.setTenantId(tenantId);
    userStatisticsDTO.setUserWorkType(userWorkType);

    //查询总出勤
    List<LobarScreenDTO> sum = userStatisticsMapper.selectPart(userStatisticsDTO);

    //查询昨天出勤
    userStatisticsDTO.setStartTime(DateUtil.beginOfDay(DateUtil.yesterday()));
    userStatisticsDTO.setEndTime(DateUtil.endOfDay(DateUtil.yesterday()));
    List<LobarScreenDTO> yesterday = userStatisticsMapper.selectPart(userStatisticsDTO);

    //查询7天出勤
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DATE,-7);
    userStatisticsDTO.setStartTime(DateUtil.beginOfDay(calendar.getTime()));
    userStatisticsDTO.setEndTime(DateUtil.endOfDay(new Date()));
    List<LobarScreenDTO> sevenDay = userStatisticsMapper.selectPart(userStatisticsDTO);
    //查询本月
    userStatisticsDTO.setStartTime(DateUtil.beginOfMonth(new Date()));
    userStatisticsDTO.setEndTime(DateUtil.endOfMonth(new Date()));
    List<LobarScreenDTO> month = userStatisticsMapper.selectPart(userStatisticsDTO);


    //最终统计
    List<LobarScreenDTO> result = new ArrayList<>();
    laborCompanyProjectDTOS.forEach(l ->{
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO();
      lobarScreenDTO.setId(l.getCompanyProjectId());
      lobarScreenDTO.setName(l.getName());
      lobarScreenDTO.setAbbreviation(l.getAbbreviation());
      //昨天
      List<String> yesParts = yesterday.stream()
          .filter(y -> l.getCompanyProjectId().equals(y.getId()))
          .map(y -> y.getPart()).collect(Collectors.toList());
      if (null != yesParts && yesParts.size() > 0){
        lobarScreenDTO.setYesterday(yesParts.get(0));
      }

      //7天
      List<String> sevenParts = sevenDay.stream()
          .filter(s -> l.getCompanyProjectId().equals(s.getId()))
          .map(s -> s.getPart()).collect(Collectors.toList());
      if (null != sevenParts && sevenParts.size() > 0){
        lobarScreenDTO.setSevenDay(sevenParts.get(0));
      }

      //本月
      List<String> monthParts = month.stream()
          .filter(m -> l.getCompanyProjectId().equals(m.getId()))
          .map(m -> m.getPart()).collect(Collectors.toList());
      if (null != monthParts && monthParts.size() > 0){
        lobarScreenDTO.setMouth(monthParts.get(0));
      }

      //总统计
      List<String> sumParts = sum.stream()
          .filter(m -> l.getCompanyProjectId().equals(m.getId()))
          .map(m -> m.getPart()).collect(Collectors.toList());
      if (null != sumParts && sumParts.size() > 0){
        lobarScreenDTO.setSum(sumParts.get(0));
      }
      result.add(lobarScreenDTO);
    });
    return result;
  }

  /**
   * 工时分析
   */
  @Override
  public HourAnalysisDTO hourAnalysis() {
    HourAnalysisDTO hourAnalysisDTO = new HourAnalysisDTO();
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();

    UserStatisticsDTO userStatisticsDTO = new UserStatisticsDTO();
    userStatisticsDTO.setTenantId(tenantId);
    //历史人均
    double sumHour = userStatisticsMapper.averageHour(userStatisticsDTO);
    hourAnalysisDTO.setSumHour(sumHour);

    //昨日人均
    userStatisticsDTO.setStartTime(DateUtil.beginOfDay(DateUtil.yesterday()));
    userStatisticsDTO.setEndTime(DateUtil.endOfDay(DateUtil.yesterday()));
    double yesterdayHour = userStatisticsMapper.averageHour(userStatisticsDTO);
    hourAnalysisDTO.setYesterdayHour(yesterdayHour);

    //本月人均
    userStatisticsDTO.setStartTime(DateUtil.beginOfMonth(new Date()));
    userStatisticsDTO.setEndTime(DateUtil.endOfMonth(new Date()));
    double monthHour = userStatisticsMapper.averageHour(userStatisticsDTO);
    hourAnalysisDTO.setMonthHour(monthHour);

    //参建单位人均
    List<LaborCompanyProjectDTO> laborCompanyProjectDTOS = laborCompanyProjectMapper.findAll(tenantId);
    //查询参建单位人均
    List<LobarScreenDTO> lobarScreenDTOS = userStatisticsMapper.companyHour(tenantId);
    List<LobarScreenDTO> companyHours = new ArrayList<>();
    laborCompanyProjectDTOS.forEach(l ->{
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO();
      lobarScreenDTO.setName(l.getName());
      List<Double> housr = lobarScreenDTOS.stream()
          .filter(lo -> l.getCompanyProjectId().equals(lo.getId()))
          .map(lo -> lo.getHours()).collect(Collectors.toList());
      if (null != housr && housr.size() > 0){
        lobarScreenDTO.setHours(housr.get(0));
      }else {
        lobarScreenDTO.setHours(0d);
      }
      companyHours.add(lobarScreenDTO);
    });
    List<LobarScreenDTO> dtoList = companyHours.stream()
        .sorted(Comparator.comparing(LobarScreenDTO::getHours).reversed())
        .collect(Collectors.toList());
    hourAnalysisDTO.setCompanyHours(dtoList);
    return hourAnalysisDTO;
  }

  /**
   * 风险预警统计
   */
  @Override
  public WarningDTO warning() {
    WarningDTO warningDTO = new WarningDTO();
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //昨天预警数
    Integer yesterday = yesterdayWarning(tenantId);
    warningDTO.setYesterday(yesterday);
    //本月预警数
    Integer month = monthWarning(tenantId);
    warningDTO.setMonth(month);
    //总预警数
    Integer sum = sumWarning(warningDTO,tenantId);
    warningDTO.setSum(sum);
    return warningDTO;
  }

  /***
   * 分类报警求和
   * @param tenantId 租户id
   * @param type 求和类型
   * @param warningDTO
   * @return 求和值
   */
  private Integer countTypeWarningNum(String tenantId, Integer type, WarningDTO warningDTO) {
    List<LobarScreenDTO> sumList = new ArrayList<>();
    Date now = DateUtil.date();
    switch (type) {
      case 1:
        now = DateUtil.offsetDay(now,-1);
        break;
      default:
        break;
    }
    Date startTime = DateUtil.beginOfDay(now);
    Date endTime = DateUtil.endOfDay(now);

    QueryWrapper<UserWarning> userWrapper = new QueryWrapper<>();
    userWrapper.eq("tenant_id_", tenantId)
            .ge("warning_time_", startTime)
            .le("warning_time_", endTime);
    Integer user = userWarningMapper.selectCount(userWrapper);
    LobarScreenDTO userDTO = new LobarScreenDTO();
    userDTO.setName("人员出勤预警");
    userDTO.setNum(user);
    sumList.add(userDTO);

    QueryWrapper<GroupWarning> groupWrapper = new QueryWrapper<>();
    groupWrapper.eq("tenant_id_", tenantId)
            .ge("warning_time_", startTime)
            .le("warning_time_", endTime);
    Integer group = groupWarningMapper.selectCount(groupWrapper);
    LobarScreenDTO groupDTO = new LobarScreenDTO();
    groupDTO.setName("班组出勤预警");
    groupDTO.setNum(group);
    sumList.add(groupDTO);

    QueryWrapper<AgeWarning> ageWrapper = new QueryWrapper<>();
    ageWrapper.eq("tenant_id_", tenantId)
            .ge("warning_time_", startTime)
            .le("warning_time_", endTime);
    Integer age = ageWarningMapper.selectCount(ageWrapper);
    LobarScreenDTO ageDTO = new LobarScreenDTO();
    ageDTO.setName("年龄预警");
    ageDTO.setNum(age);
    sumList.add(ageDTO);

    QueryWrapper<CertificateWarning> certificateWrapper = new QueryWrapper<>();
    certificateWrapper.eq("tenant_id_", tenantId)
            .ge("warning_time_", startTime)
            .le("warning_time_", endTime);
    Integer certificate = certificateWarningMapper.selectCount(certificateWrapper);
    LobarScreenDTO certificateDTO = new LobarScreenDTO();
    certificateDTO.setName("证书预警");
    certificateDTO.setNum(certificate);
    sumList.add(certificateDTO);

    //20221021 需求1005345 【WEB/劳务管理】人员出场异常预警
    QueryWrapper<UserOutinWarning> outinQueryWrapper = new QueryWrapper<>();
    outinQueryWrapper.eq("tenant_id_", tenantId)
            .ge("warning_time_", startTime)
            .le("warning_time_", endTime);
    Integer outin = userOutinWarningMapper.selectCount(outinQueryWrapper);
    LobarScreenDTO outinDTO = new LobarScreenDTO();
    outinDTO.setName("人员出场异常预警");
    outinDTO.setNum(outin);
    sumList.add(outinDTO);

    //20221206 需求1005546【APP/劳务管理】补充疫情监测预警消息+大屏增加疫情预警
    QueryWrapper<EpidemicWarning> epidemicQueryWrapper = new QueryWrapper<>();
    epidemicQueryWrapper.eq("tenant_id_", tenantId)
        .ge("warning_time_", startTime)
        .le("warning_time_", endTime);
    Integer epidemic = epidemicWarningMapper.selectCount(epidemicQueryWrapper);
    LobarScreenDTO epidemicDTO = new LobarScreenDTO();
    epidemicDTO.setName("疫情监测预警");
    epidemicDTO.setNum(epidemic);
    sumList.add(epidemicDTO);

    //降序排序
    List<LobarScreenDTO> dtoList = sumList.stream()
            .sorted(Comparator.comparing(LobarScreenDTO::getNum).reversed())
            .collect(Collectors.toList());
    warningDTO.setCompanyHours(dtoList);

    return user + group + age + certificate + outin + epidemic;
  }

  @Resource
  private VisitorRecordMapper visitorRecordMapper;

  /**
   * 在场人数
   * type有值表示需要过滤，取分包单位数据
   * @return
   */
  @Override
  public Map<String, Integer> onNum(Integer type,String tenantId) {
    Map<String, Integer> map = new HashMap<>();
    if(StringUtils.isBlank(tenantId)){
      tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    }
    Date date = new Date();
    DateTime begin = DateUtil.beginOfDay(date);
    DateTime end = DateUtil.endOfDay(date);
    Boolean filter = isFilter(tenantId);
    //实时人数
    Set<String> hourSet = getOnNum(tenantId,DateUtil.beginOfHour(date),DateUtil.endOfHour(
        date),type,filter);
    map.put("hour",hourSet.size());
    //本日进场数
    Set<String> datSet = getOnNum(tenantId,begin, end,type,filter);
    map.put("day",datSet.size());
    //本日出勤数
    List<String> attendance = getAttendance(tenantId,begin, end,type,filter);
    map.put("attendance",attendance.size());
    //在场总人数
    QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_",tenantId)
        .eq("status_",1);

    //type 不为空时过滤
    if (null != type && filter){
      filterByType(tenantId,queryWrapper);
    }
    Integer integer = userProjectMapper.selectCount(queryWrapper);
    map.put("sum",integer);

    //访客人数
    VisitorRecordDTO visitorRecordDTO = new VisitorRecordDTO();
    visitorRecordDTO.setStartTime(begin);
    visitorRecordDTO.setEndTime(end);
    visitorRecordDTO.setTenantId(tenantId);
    Integer visitorCount = visitorRecordMapper.countByIdCard(visitorRecordDTO);
    map.put("visitorCount",visitorCount);
    return map;
  }

  /**
   * 7天出勤率
   * @param userWorkType 人员类型 1:作业人员 2:管理人员
   */
  @Override
  public List<UserStatistics> sevenAttendance(Integer userWorkType) {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //查询7天内的数据
    List<UserStatistics> userStatisticsList = userStatisticsMapper.findSevenAttendance(tenantId);

    //查询当天
    QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_", tenantId);
    queryWrapper.eq("status_",1).eq("delete_state_",1);
    List<UserProject> projects = userProjectMapper.selectList(queryWrapper);
    //工种
    if (Integer.valueOf(1).equals(userWorkType)){
      projects.removeIf(u-> LobarUtils.isManager(u.getWorkType()));
    }else if (Integer.valueOf(2).equals(userWorkType)){
      projects.removeIf(u-> !LobarUtils.isManager(u.getWorkType()));
    }
    List<String> userIds = projects.stream().map(UserProject::getUserId).collect(Collectors.toList());

    //考勤
    QueryWrapper<UserRecord> recordQueryWrapper = new QueryWrapper<>();
    recordQueryWrapper
        .ne("record_type_",0)
        .in("user_id_",userIds)
        //7天内数据 多查一天
        .ge("record_time_",DateUtil.beginOfDay(DateUtil.offsetDay(new Date(),-7)))
        .le("record_time_",DateUtil.endOfDay(new Date()))
        .eq("tenant_id_",tenantId);
    List<UserRecord> userRecords = userRecordMapper.selectList(recordQueryWrapper);


    List<UserStatistics> rerult = new ArrayList<>();
    for (int i = 0; i < 7; i++) {
      Calendar calendar = DateUtil.beginOfDay(Calendar.getInstance());
      UserStatistics userStatistics = new UserStatistics();
      calendar.add(Calendar.DAY_OF_YEAR,-i);
      int size = userRecords.stream()
              .filter(u -> u.getRecordTime().equals(calendar.getTime()))
              .collect(Collectors.toList()).size();
      if (i == 0){
        userStatistics.setOn(size);
        userStatistics.setSum(userIds.size());
      }else {
        List<UserStatistics> dtos = userStatisticsList.stream()
            .filter(u -> u.getRecordTime().equals(calendar.getTime()))
            .collect(Collectors.toList());
        if (dtos.size()>0){
          //按工种处理
          if (Integer.valueOf(1).equals(userWorkType)){
            userStatistics.setOn(size);
            userStatistics.setSum(dtos.get(0).getWork());
          }else if (Integer.valueOf(2).equals(userWorkType)){
            userStatistics.setOn(size);
            userStatistics.setSum(dtos.get(0).getManage());
          }else {
            userStatistics.setOn(dtos.get(0).getOn());
            userStatistics.setSum(dtos.get(0).getSum());
          }
        }else {
          userStatistics.setOn(0);
          userStatistics.setSum(0);
        }
      }
      userStatistics.setRecordTime(calendar.getTime());
      rerult.add(userStatistics);
    }
    return rerult.stream().sorted(Comparator.comparing(UserStatistics::getRecordTime)).collect(Collectors.toList());
  }

  /**
   * 出勤分析
   */
  @Override
  public List<LobarUserDTO> analysisMonth() {
    List<LobarUserDTO> result = new ArrayList<>();
    //查询30天的数据
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    List<LobarUserDTO> list = userRecordMapper.analysisMonth(tenantId);
    for (int i = 0; i < 30; i++) {
      Calendar calendar = DateUtil.beginOfDay(Calendar.getInstance());
      LobarUserDTO lobarUserDTO = new LobarUserDTO();
      calendar.add(Calendar.DAY_OF_YEAR,-i);
      List<LobarUserDTO> userDTOS = list.stream()
          .filter(u -> u.getRecordTime().equals(calendar.getTime()))
          .collect(Collectors.toList());
      if (userDTOS.size()>0){
        lobarUserDTO.setAttendance(userDTOS.get(0).getAttendance());
      }else {
        lobarUserDTO.setAttendance(0);
      }
      lobarUserDTO.setRecordTime(calendar.getTime());
      result.add(lobarUserDTO);
    }
    return result;
  }

  /**
   * 按工种统计
   */
  @Override
  public List<LobarUserDTO> getAttnByWorkType() {
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    //查询所有在场人员
    QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_",tenantId)
        .eq("status_",1);
    List<UserProject> userProjects = userProjectMapper.selectList(queryWrapper);
    Map<String, List<UserProject>> map = userProjects.stream().filter(u->StringUtils.isNotBlank(u.getWorkType())).collect(Collectors
        .groupingBy(u -> u.getWorkType()));

    //今日出勤
//    List<UserClockDTO> byToday = userClockMapper.getByToday(tenantId);
    List<UserRecordDTO> byToday = userRecordMapper.getByToday(tenantId);
    List<LobarUserDTO> list = new ArrayList<>();
    map.forEach((key,value) ->{
      LobarUserDTO lobarUserDTO = new LobarUserDTO();
      //求userId集合
      Set<String> userIds = value.stream().map(u -> u.getUserId()).collect(Collectors.toSet());
      lobarUserDTO.setName(key.substring(key.lastIndexOf("/")+1));
      //出勤
      long count1 = byToday.stream().filter(b -> null != b.getRecordType() && !Integer.valueOf(0).equals(b.getRecordType())
          && userIds.contains(b.getUserId())).count();
      lobarUserDTO.setAttendance((int)count1);
      //总人数
      lobarUserDTO.setIn(value.size());
      lobarUserDTO.setPart(PercentageUtils.computePercentOne((int)count1,value.size()));
      list.add(lobarUserDTO);
    });
    //总人日
    return list.stream().sorted(Comparator.comparing(LobarUserDTO::getIn).reversed()).collect(
        Collectors.toList());
  }

  /**
   * 出勤统计
   */
  @Override
  public List<AppUserGateDTO> statistics() {
    List<AppUserGateDTO> userGateDTOS = userClockService.getCompany(new Date());
    //求总数
    int sum = userGateDTOS.stream().mapToInt(u -> u.getSum()).sum();
    int attendance = userGateDTOS.stream().mapToInt(u -> u.getAttendance()).sum();
    //根据参建单位类型区分
//    13 施工单位
//    1 2分包单位
    //施工单位数据
    Set<String> ids13 = userGateDTOS.stream().filter(u -> "13".equals(u.getBuildType()))
        .map(u -> u.getCompanyProjectId()).collect(Collectors.toSet());
    int sum13 = userGateDTOS.stream().filter(u -> "13".equals(u.getBuildType()))
        .mapToInt(u -> u.getSum()).sum();
    int attendance13 = userGateDTOS.stream().filter(u -> "13".equals(u.getBuildType()))
        .mapToInt(u -> u.getAttendance()).sum();
    //分包单位数据
    Set<String> ids12 = userGateDTOS.stream()
        .filter(u -> "1".equals(u.getBuildType()) || "2".equals(u.getBuildType()))
        .map(u -> u.getCompanyProjectId()).collect(Collectors.toSet());
    int sum12 = userGateDTOS.stream()
        .filter(u -> "1".equals(u.getBuildType()) || "2".equals(u.getBuildType()))
        .mapToInt(u -> u.getSum()).sum();
    int attendance12 = userGateDTOS.stream()
        .filter(u -> "1".equals(u.getBuildType()) || "2".equals(u.getBuildType()))
        .mapToInt(u -> u.getAttendance()).sum();
    //汇总
    List<AppUserGateDTO> result = new ArrayList<>();
    AppUserGateDTO user13 = new AppUserGateDTO("施工单位",sum13,attendance13);
    AppUserGateDTO user12 = new AppUserGateDTO("分包单位",sum12,attendance12);
    AppUserGateDTO other = new AppUserGateDTO("其他",sum-sum13-sum12,attendance-attendance13-attendance12);
    //求场内人员
//    List<UserRecordDTO> byToday = userRecordMapper
//        .getByToday(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    List<UserProjectDTO> projectList = userProjectMapper
        .getOnArea(linkappUserContextProducer.getNotNullCurrent().getTenantId(), null);

//    List<UserClockDTO> byToday = userClockMapper
//        .getByToday(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    long count = projectList.stream().filter(b -> null != b.getOnArea() && !Integer.valueOf(4).equals(b.getOnArea())).count();
    long count13 = projectList.stream().filter(b -> null != b.getOnArea() && !Integer.valueOf(4).equals(b.getOnArea()) && ids13.contains(b.getCompanyProjectId())).count();
    long count12 = projectList.stream().filter(b -> null != b.getOnArea() && !Integer.valueOf(4).equals(b.getOnArea()) && ids12.contains(b.getCompanyProjectId())).count();
    user13.setOn((int)count13);
    user12.setOn((int)count12);
    other.setOn((int)count-(int)count13-(int)count12);
    result.add(user13);result.add(user12);result.add(other);
    return result;
  }

  /**
   * 参建单位统计
   */
  @Override
  public List<AppUserGateDTO> getByCompany() {
    List<AppUserGateDTO> userGateDTOS = userClockService.getCompany(new Date());
    //过滤掉其他
    userGateDTOS.removeIf(
        u-> !"1".equals(u.getBuildType()) && !"2".equals(u.getBuildType()) && !"13".equals(u.getBuildType()));
    //求场内人员
//    List<UserClockDTO> byToday = userClockMapper
//        .getByToday(linkappUserContextProducer.getNotNullCurrent().getTenantId());
    List<UserRecordDTO> byToday = userRecordMapper
        .getByToday(linkappUserContextProducer.getNotNullCurrent().getTenantId());

    userGateDTOS.forEach(u->{
      long count = byToday.stream()
          .filter(b -> null != b.getOnArea() && !Integer.valueOf(4).equals(b.getOnArea()) && u.getCompanyProjectId().equals(b.getCompanyProjectId()))
          .count();
      u.setOn((int)count);
    });
    return userGateDTOS;
  }

  /**
   * 最新出勤
   */
  @Override
  public List<UserProjectDTO> newAttention() {
    List<UserProjectDTO> list = userClockMapper.findNewAttention(linkappUserContextProducer.getNotNullCurrent().getTenantId(),20);
    return list;
  }

  /**
   * 最新进场
   */
  @Override
  public List<UserProjectDTO> newJoin() {
    List<UserProjectDTO> list = userProjectMapper.findNewJoin(linkappUserContextProducer.getNotNullCurrent().getTenantId(),20);
    return list;
  }

  @Override
  public WarningDTO lobarWarning(LobarScreenWarnVo lobarScreenWarnVo) {
    WarningDTO warningDTO = new WarningDTO();
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    Integer dataType = lobarScreenWarnVo.getDataType();
    //昨天预警数
    Integer sum = countTypeWarningNum(tenantId,dataType,warningDTO);
    //总预警数
    warningDTO.setSum(sum);
    return warningDTO;
  }

  /**
   * 人员分布分析
   */
  @Override
  public Map<String, List<LobarScreenDTO>> countAllUser(String tenantId, String companyId) {
    Map<String, List<LobarScreenDTO>> map = new HashMap<>();
    List<String> buildTypes = new ArrayList<>();
    //在场人数
    List<UserProjectDTO> userProjects = userProjectMapper.countUser2(tenantId,buildTypes,companyId);
    List<LobarScreenDTO> ages = listGroupByAgePeriod(userProjects);

//    List<UserProjectDTO> dtos6 = userProjects.stream()
//        .filter(u ->DateUtil.age(u.getBirthday(), new Date()) >= 60)
//        .collect(Collectors.toList());
//    LobarScreenDTO lobarScreenDTO6 = new LobarScreenDTO("60岁-65岁",dtos6.size());
//    ages.add(lobarScreenDTO6);
    ages.forEach(a->{
      a.setPart(PercentageUtils.computePercentTwo(a.getNum(),userProjects.size()));
    });
    map.put("age",ages);
    //籍贯
    Map<String, List<UserProjectDTO>> nativeMap = userProjects.stream()
        .filter(u->StringUtils.isNotBlank(u.getCard()))
        .collect(Collectors.groupingBy(c -> getNative(c.getCard())));
    List<LobarScreenDTO> natives = new ArrayList<>();
    nativeMap.forEach((k,v) ->{
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO(k,v.size());
      natives.add(lobarScreenDTO);
    });
    List<LobarScreenDTO> dtoList = natives.stream()
        .sorted(Comparator.comparing(LobarScreenDTO::getNum).reversed())
        .collect(Collectors.toList());
    dtoList.forEach(a->{
      a.setPart(PercentageUtils.computePercentTwo(a.getNum(),userProjects.size()));
    });
    map.put("native",dtoList);
    return map;
  }

  @Override
  public List<LobarScreenDTO> listGroupByAgePeriod(String tenantId, String companyId) {
    List<UserProjectDTO> userProjects = userProjectMapper.countUser2(tenantId, new ArrayList<>(), companyId);
    List<LobarScreenDTO> ages = listGroupByAgePeriod(userProjects);
    ages.forEach(a -> {
      a.setPart(PercentageUtils.computePercentTwo(a.getNum(), userProjects.size()));
    });
    return ages;
  }

  @Override
  public List<UserCountByProjectDTO> listUserCountByProject(String companyId) {
    List<UserCountByProjectDTO> userCountByProjectDTOS = userProjectMapper.listUserCountByProject(companyId);
    return userCountByProjectDTOS;
  }

  @Override
  public List<UserCountByWorkDTO> listUserCountByWork(String companyId) {
    List<UserCountByWorkDTO> userCountByWorkDTOS = userProjectMapper.listUserCountByWork(companyId);
    //求百分比
    long sum = userCountByWorkDTOS.stream().mapToLong(UserCountByWorkDTO::getCount).sum();
    userCountByWorkDTOS.forEach(u -> {
      u.setPercent(new BigDecimal(u.getCount() * 100).setScale(2, RoundingMode.HALF_UP).divide(BigDecimal.valueOf(sum), RoundingMode.HALF_UP));
    });
    return userCountByWorkDTOS;
  }

  private List<LobarScreenDTO> listGroupByAgePeriod(List<UserProjectDTO> userProjects) {
    //年龄
    List<LobarScreenDTO> ages = new ArrayList<>();
    List<UserProjectDTO> dtos2 = userProjects.stream()
        .filter(u ->DateUtil.age(u.getBirthday(), new Date()) >= 18 && DateUtil.age(u.getBirthday(), new Date()) < 30)
        .collect(Collectors.toList());
    LobarScreenDTO lobarScreenDTO2 = new LobarScreenDTO("18-30岁",dtos2.size());
    ages.add(lobarScreenDTO2);

    List<UserProjectDTO> dtos3 = userProjects.stream()
        .filter(u ->DateUtil.age(u.getBirthday(), new Date()) >= 30 && DateUtil.age(u.getBirthday(), new Date()) < 40)
        .collect(Collectors.toList());
    LobarScreenDTO lobarScreenDTO3 = new LobarScreenDTO("30-40岁",dtos3.size());
    ages.add(lobarScreenDTO3);

    List<UserProjectDTO> dtos4 = userProjects.stream()
        .filter(u ->DateUtil.age(u.getBirthday(), new Date()) >= 40 && DateUtil.age(u.getBirthday(), new Date()) < 50)
        .collect(Collectors.toList());
    LobarScreenDTO lobarScreenDTO4 = new LobarScreenDTO("40-50岁",dtos4.size());
    ages.add(lobarScreenDTO4);
    List<UserProjectDTO> dtos5 = userProjects.stream()
            .filter(u ->DateUtil.age(u.getBirthday(), new Date()) >= 50 && DateUtil.age(u.getBirthday(), new Date()) < 60)
            .collect(Collectors.toList());
    LobarScreenDTO lobarScreenDTO5 = new LobarScreenDTO("50-60岁",dtos5.size());
    ages.add(lobarScreenDTO5);
    return ages;
  }

  /**
   * 作业人员统计
   */
  @Override
  public Map<String, List<LobarScreenDTO>> countWorkType(String tenantId) {
    Map<String, List<LobarScreenDTO>> map = new HashMap<>();
    //查询当天所有的考勤记录
    String workTypeName = "作业人员";
    List<UserProject> userProjects = userRecordMapper.countWorkTypeToDay(null,tenantId);
    //过滤非管理人员
    List<UserProject> otherUserProjects = userProjects.stream()
        .filter(u -> StringUtils.isNotBlank(u.getWorkType()) && !u.getWorkType().startsWith("管理人员"))
        .collect(Collectors.toList());
    //第三级再分组
    List<LobarScreenDTO> otherlobarScreenDTOS = new ArrayList<>();
    Map<String, List<UserProject>> otherSonMap = otherUserProjects.stream().filter(u->StringUtils.isNotBlank(u.getWorkType()))
        .collect(Collectors.groupingBy(c -> c.getWorkType()
            .substring(c.getWorkType().lastIndexOf("/") + 1)));
    otherSonMap.forEach((key,value) ->{
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO();
      lobarScreenDTO.setName(key);
      //出勤人数
      lobarScreenDTO.setNum(value.size());
      otherlobarScreenDTOS.add(lobarScreenDTO);
    });
    map.put("工种",otherlobarScreenDTOS.stream().sorted(Comparator.comparing(LobarScreenDTO::getNum).reversed()).collect(Collectors.toList()));


    //过滤作业人员
    List<UserProject> zyUserProjects = userProjects.stream().filter(
        u -> StringUtils.isNotBlank(u.getWorkType()) && u.getWorkType().startsWith(workTypeName))
        .collect(Collectors.toList());
    //分类
    Map<String, List<UserProject>> listMap = zyUserProjects.stream().filter(u->StringUtils.isNotBlank(u.getWorkType())).collect(Collectors.groupingBy(
        u -> u.getWorkType()
            .substring(u.getWorkType().indexOf("/") + 1, u.getWorkType().lastIndexOf("/"))));
    listMap.forEach((k,v)->{
      List<LobarScreenDTO> lobarScreenDTOS = new ArrayList<>();
      //第三级再分组
      Map<String, List<UserProject>> sonMap = v.stream().filter(u->StringUtils.isNotBlank(u.getWorkType()))
          .collect(Collectors.groupingBy(c -> c.getWorkType()
              .substring(c.getWorkType().lastIndexOf("/") + 1)));
      sonMap.forEach((key,value) ->{
        LobarScreenDTO lobarScreenDTO = new LobarScreenDTO();
        lobarScreenDTO.setName(key);
        //出勤人数
        lobarScreenDTO.setNum(value.size());
        lobarScreenDTOS.add(lobarScreenDTO);
      });
      map.put(k,lobarScreenDTOS.stream().sorted(Comparator.comparing(LobarScreenDTO::getNum).reversed()).collect(Collectors.toList()));
    });
    return map;
  }

  /**
   * 项目详情
   */
  @Override
  public IPage<LinkappTenantDTO> countProject(RequestModel<UserProjectDTO> requestModel) {
    Page page = requestModel.getPage();
    UserProjectDTO queryParams = requestModel.getCustomQueryParams();
    //查询所有项目
    IPage<LinkappTenantDTO> iPage = linkappTenantMapper.selectByName(page,queryParams);

    //获取项目tenantIds集合
    List<String> ids = iPage.getRecords().stream().map(i -> i.getId())
        .collect(Collectors.toList());
    queryParams.setTenantIds(ids);
    List<UserRecord> userRecords;
    List<UserProjectDTO> userProjectDTOS;
    List<UserProjectDTO> onUserProjectDTOS = new ArrayList<>();
    DateTime dateTime = DateUtil.beginOfDay(new Date());
    if (null == queryParams.getStartTime() || queryParams.getStartTime().equals(dateTime)){
      //求当天的在场人员
      userProjectDTOS = userProjectMapper.findByTenantId2(queryParams);
      //当天进场人数
      onUserProjectDTOS = userProjectMapper.findOnByTenantId2(queryParams);
      //求当天所有的出勤人员
      QueryWrapper<UserRecord> queryWrapper = new QueryWrapper<>();
      queryWrapper.ne("record_type_",0).ge("record_time_",DateUtil.beginOfDay(new Date()))
          .le("record_time_",DateUtil.endOfDay(new Date()));
      if (StringUtils.isNotBlank(queryParams.getTenantId())){
        queryWrapper.eq("tenant_id_",queryParams.getTenantId());
      }
      userRecords = userRecordMapper.selectList(queryWrapper);
    }else {
      //在场
      userProjectDTOS = userRecordMapper.selectByTenantId(queryParams);
      //出勤
      List<UserProjectDTO> projectDTOList = userProjectDTOS.stream()
          .filter(u -> !Integer.valueOf(0).equals(u.getRecordType())).collect(Collectors.toList());
      //转化
      List<UserRecord> userRecords2 = new ArrayList<>();
      projectDTOList.forEach(p->{
        UserRecord userRecord = new UserRecord();
        userRecord.setTenantId(p.getTenantId());
        userRecord.setUserId(p.getUserId());
        userRecords2.add(userRecord);
      });
      userRecords = userRecords2;
    }

    //项目部管理人员
    List<UserProjectDTO> projectUsers = userProjectDTOS.stream()
        .filter(u -> "13".equals(u.getBuildType()) && StringUtils.isNotBlank(u.getWorkType()) && u.getWorkType().startsWith("管理人员")).collect(Collectors.toList());
    List<UserProjectDTO> onProjectUsers = onUserProjectDTOS.stream()
        .filter(u -> "13".equals(u.getBuildType()) && StringUtils.isNotBlank(u.getWorkType()) && u.getWorkType().startsWith("管理人员")).collect(Collectors.toList());
    //其他管理人员
    List<UserProjectDTO> otherProUsers = userProjectDTOS.stream()
        .filter(u -> !"13".equals(u.getBuildType()) && StringUtils.isNotBlank(u.getWorkType()) && u.getWorkType().startsWith("管理人员")).collect(Collectors.toList());
    List<UserProjectDTO> onOtherProUsers = onUserProjectDTOS.stream()
        .filter(u -> !"13".equals(u.getBuildType()) && StringUtils.isNotBlank(u.getWorkType()) && u.getWorkType().startsWith("管理人员")).collect(Collectors.toList());
    //现场作业人员
    List<UserProjectDTO> workProUsers = userProjectDTOS.stream()
        .filter(u -> StringUtils.isBlank(u.getWorkType()) || !u.getWorkType().startsWith("管理人员")).collect(Collectors.toList());
    List<UserProjectDTO> onWorkProUsers = onUserProjectDTOS.stream()
        .filter(u -> StringUtils.isBlank(u.getWorkType()) || !u.getWorkType().startsWith("管理人员")).collect(Collectors.toList());

    //组织各项目数据
    List<UserRecord> finalUserRecords = userRecords;
    iPage.getRecords().forEach(l->{
      if (null == l.getProjectAmount()){
        l.setProjectAmount(0d);
      }
      //计算剩余工期
      if (null != l.getCompletionTime()){

        long between = DateUtil.between(new Date(), DateUtil.endOfDay(l.getCompletionTime()),
            DateUnit.DAY,false);
        l.setSurplusDay(between);
      }
      //组织在场/出勤数据
      List<LobarUserDTO> lobarUserDTOS = new ArrayList<>();
      //项目部管理人员
      getUses(finalUserRecords, projectUsers, onProjectUsers,l, lobarUserDTOS,"项目部管理人员");
      //其他管理人员
      getUses(finalUserRecords, otherProUsers,onOtherProUsers, l, lobarUserDTOS,"其他管理人员");
      //现场作业人员
      getUses(finalUserRecords, workProUsers,onWorkProUsers, l, lobarUserDTOS,"现场作业人员");
//      getProUsers(finalUserRecords, userProjectDTOS, finalOnUserProjectDTOS1, l, lobarUserDTOS,"现场作业人员");
      l.setLobarUserDTOS(lobarUserDTOS);
      l.setIn(lobarUserDTOS.stream().mapToInt(lo->lo.getIn()).sum());
      l.setAttendance(lobarUserDTOS.stream().mapToInt(lo->lo.getAttendance()).sum());
    });
    //场内人员统计
    List<Map<String, Object>> onAreas = getOnArea();
    iPage.getRecords().forEach(i ->{
      List<Map<String, Object>> mapList = onAreas.stream()
          .filter(o -> ((String) o.get("tenantId")).equals(i.getId()))
          .collect(Collectors.toList());
      if (mapList.size() > 0){
        i.setOnAreas(mapList.get(0));
      }
    });
    iPage.setRecords(iPage.getRecords().stream().
        sorted(Comparator.comparing(LinkappTenantDTO::getProjectAmount)
            .thenComparing(LinkappTenantDTO::getIn).reversed()).
        collect(Collectors.toList()));
    return iPage;
  }

  private List<Map<String, Object>> getOnArea() {
    List<Map<String, Object>> result = new ArrayList<>();
    List<Integer> list = new ArrayList<>();
    list.add(1);list.add(2);list.add(3);
    QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("delete_state_",1)
        .eq("status_",1)
        .in("on_area_",list);
    List<UserProject> userProjects = userProjectMapper.selectList(queryWrapper);
    //按tenantId分组
    Map<String, List<UserProject>> listMap = userProjects.stream()
        .collect(Collectors.groupingBy(u -> u.getTenantId()));
    listMap.forEach((k,v) ->{
      //施工区
      long count1 = v.stream().filter(u -> Integer.valueOf(1).equals(u.getOnArea()))
          .count();
      //办公区
      long count2 = v.stream().filter(u -> Integer.valueOf(2).equals(u.getOnArea()))
          .count();
      //生活区
      long count3 = v.stream().filter(u -> Integer.valueOf(3).equals(u.getOnArea()))
          .count();
      Map<String, Object> map = new HashMap<>();
      map.put("tenantId",k);
      map.put("1",(int)count1);
      map.put("2",(int)count2);
      map.put("3",(int)count3);
      result.add(map);
    });
    return result;
  }

  //现场作业人员
  private void getProUsers(List<UserRecord> finalUserRecords, List<UserProjectDTO> userProjectDTOS, List<UserProjectDTO> onProUsers, LinkappTenantDTO l, List<LobarUserDTO> lobarUserDTOS, String name) {
    int aCount = (int)finalUserRecords.stream().filter(r -> l.getId().equals(r.getTenantId())).count();
    int iCount = (int)userProjectDTOS.stream().filter(u -> l.getId().equals(u.getTenantId())).count();
    int oCount = (int)onProUsers.stream().filter(o -> l.getId().equals(o.getTenantId())).count();
    LobarUserDTO lobarUserDTO = new LobarUserDTO();
    lobarUserDTO.setName(name);
    lobarUserDTO.setOn(oCount-lobarUserDTOS.stream().mapToInt(u->u.getOn()).sum());
    lobarUserDTO.setAttendance(aCount-lobarUserDTOS.stream().mapToInt(u->u.getAttendance()).sum());
    lobarUserDTO.setIn(iCount-lobarUserDTOS.stream().mapToInt(u->u.getIn()).sum());
    lobarUserDTO.setPart(PercentageUtils.computePercentTwo(aCount,iCount));
    lobarUserDTOS.add(lobarUserDTO);
  }

  /**
   * 当日疫情分析
   */
  @Override
  public List<Map<String, Object>> countEpidemic(String tenantId) {
    //查询所有项目
    List<LinkappTenant> list = linkappTenantMapper.selectByProjectId(null);
    list.removeIf(l -> "1".equals(l.getId()));
    //查询疫情预警情况
    QueryWrapper<EpidemicWarning> queryWrapper = new QueryWrapper<>();
    queryWrapper.le("warning_time_",DateUtil.endOfDay(new Date()))
        .ge("warning_time_",DateUtil.beginOfDay(new Date()));
    List<EpidemicWarning> warningList = epidemicWarningMapper.selectList(queryWrapper);
    List<Map<String, Object>> newList = new ArrayList<>();
    if (StringUtils.isNotBlank(tenantId)){
      list = list.stream().filter(l->tenantId.equals(l.getId())).collect(Collectors.toList());
    }
    list.forEach(l->{
      Map<String, Object> map = new HashMap<>();
      map.put("name",l.getPlatformProjectName());
      Set<String> set1 = warningList.stream().filter(w -> !Integer.valueOf(2).equals(w.getType())
          && l.getId().equals(w.getTenantId())).map(w -> w.getUserId()).collect(Collectors.toSet());
      map.put("a",set1.size());
      Set<String> set2 = warningList.stream().filter(w -> !Integer.valueOf(1).equals(w.getType())
          && l.getId().equals(w.getTenantId())).map(w -> w.getUserId()).collect(Collectors.toSet());
      map.put("b",set2.size());
      newList.add(map);
    });
    newList.sort((a,b) ->{
      int i = (int)a.get("a");
      int j = (int)b.get("a");
      if (i>j){
        return -1;
      }else if (i<j){
        return 1;
      }else {
        int i1 = (int)a.get("b");
        int j2 = (int)b.get("b");
        if (i1>j2){
          return -1;
        }else {
          return 1;
        }
      }
    });
    return newList;
  }

  /**
   * 参建单位分析
   */
  @Override
  public List<Map<String, Object>> countCompany(String tenantId) {
    List<Map<String, Object>> list = laborCompanyMapper.countCompany(tenantId);
    UserProjectDTO userProjectDTO = new UserProjectDTO();
    userProjectDTO.setTenantId(tenantId);
    List<UserProjectDTO> userProjectDTOS = userProjectMapper.findByTenantId2(userProjectDTO);
    list.forEach(l->{
      String name = (String) l.get("name");
      int size = userProjectDTOS.stream().filter(u -> name.equals(u.getCompanyName()))
          .map(u -> u.getUserId()).collect(Collectors.toList()).size();
      l.put("b",size);
    });
    list.sort((a,b) ->{
      Long i = (Long)a.get("a");
      Long j = (Long)b.get("a");
      if (i>j){
        return -1;
      }else if (i<j){
        return 1;
      }else {
        Integer i1 = (Integer)a.get("b");
        Integer j2 = (Integer)b.get("b");
        if (i1>j2){
          return -1;
        }else if (i1<j2){
          return 1;
        }else {
          return 0;
        }
      }
    });
    return list;
  }

  @Override
  public Map<String, Integer> countAppCompany() {
    Map<String, Integer> map = new HashMap<>();
//    Map<String,Integer> map = new HashMap<>();
//    map.put("专业分包",1);map.put("劳务分包",2);map.put("设备分包",3);
//    map.put("材料分包",4);map.put("后勤服务",5);map.put("特种设备",6);
//    map.put("监理单位",7);map.put("勘查单位",8);map.put("设计单位",9);
//    map.put("租赁",10);map.put("其他",11);map.put("建设单位",12);
//    map.put("施工单位",13);
    List<Map<String, Object>> list = laborCompanyMapper.countCompany(null);
    long buildType2 = list.stream().filter(l -> "2".equals(l.get("buildType")))
        .count();
    long buildType1 = list.stream().filter(l -> "1".equals(l.get("buildType")))
        .count();
    map.put("2",(int)buildType2);
    map.put("1",(int)buildType1);
    map.put("3",list.size()-(int)buildType2-(int)buildType1);
    return map;
  }

  /**
   * 防疫统计 app
   */
  @Override
  public Map<String, Object> countAppEpidemic() {
    Map<String, Object> map = new HashMap<>();
    //统计异常
    //查询疫情预警情况
    QueryWrapper<EpidemicWarning> queryWrapper = new QueryWrapper<>();
    queryWrapper.le("warning_time_",DateUtil.endOfDay(new Date()))
        .ge("warning_time_",DateUtil.beginOfDay(new Date()));
    List<EpidemicWarning> warningList = epidemicWarningMapper.selectList(queryWrapper);
    Set<String> set1 = warningList.stream().filter(w -> !Integer.valueOf(2).equals(w.getType()))
        .map(w -> w.getUserId()).collect(Collectors.toSet());
    //体温异常
    map.put("temperatureError",set1.size());
    Set<String> set2 = warningList.stream().filter(w -> !Integer.valueOf(1).equals(w.getType()))
        .map(w -> w.getUserId()).collect(Collectors.toSet());
    //健康码异常
    map.put("healthError",set2.size());
    //统计所有打卡
    QueryWrapper<UserGate> gateQueryWrapper = new QueryWrapper<>();
    gateQueryWrapper.ge("time_",DateUtil.beginOfDay(new Date()))
        .le("time_",DateUtil.endOfDay(new Date()));
//    List<UserGate> userGates = userGateMapper.selectList(gateQueryWrapper);
//    int size = userGates.stream().map(u -> u.getUserId()).collect(Collectors.toSet()).size();
    Integer integer = userGateMapper.selectCount(gateQueryWrapper);
    //体温异常
    map.put("temperatureSuc",integer-set1.size());
    //健康码正常
    map.put("healthSuc",integer-set2.size());
    return map;
  }

  /**
   * 参建单位分析详情 app端
   */
  @Override
  public IPage<EnterpriseDTO> countAppCompanyDetail(RequestModel<UserProjectDTO> requestModel) {
    UserProjectDTO customQueryParams = requestModel.getCustomQueryParams();
    Page page = requestModel.getPage();
    //采用内存分页算了。排序不好弄
    IPage<EnterpriseDTO> iPage = laborCompanyMapper.countCompanyPage(page,customQueryParams.getCompanyName());
    List<UserProjectDTO> userProjectDTOS = userProjectMapper.findByCompany();
    iPage.getRecords().forEach(r->{
      List<UserProjectDTO> dtoList = userProjectDTOS.stream()
          .filter(u -> r.getName().equals(u.getCompanyName()))
          .collect(Collectors.toList());
//      long count = dtoList.stream().filter(d -> StringUtils.isNotBlank(d.getId())).count();
      int size = dtoList.stream().filter(d -> StringUtils.isNotBlank(d.getId()))
          .map(d -> d.getUserId()).collect(Collectors.toSet()).size();
      r.setUserNum(size);
      toCover(dtoList,r);
    });
    List<EnterpriseDTO> dtoList = iPage.getRecords().stream()
        .sorted(Comparator.comparing(EnterpriseDTO::getProjectNum).reversed()
            .thenComparing(Comparator.comparing(EnterpriseDTO::getUserNum).reversed()))
        .collect(Collectors.toList());
    iPage.setRecords(dtoList);
    return iPage;
  }

  /**
   * 防疫统计详情 app端
   */
  @Override
  public IPage<EpidemicDTO> countAppEpidemicDetail(RequestModel<UserProjectDTO> requestModel) {
    Page page = requestModel.getPage();
    UserProjectDTO customQueryParams = requestModel.getCustomQueryParams();
    customQueryParams.setId(null);
    //查询所有项目
    IPage<EpidemicDTO> newIPage = new Page<>();

    IPage<LinkappTenantDTO> iPage = linkappTenantMapper.selectByName(page,customQueryParams);
    newIPage.setTotal(iPage.getTotal());
    newIPage.setSize(iPage.getSize());
    newIPage.setPages(iPage.getPages());
    newIPage.setCurrent(iPage.getCurrent());
    //查询疫情预警情况
    QueryWrapper<EpidemicWarning> queryWrapper = new QueryWrapper<>();
    queryWrapper.le("warning_time_",DateUtil.endOfDay(new Date()))
        .ge("warning_time_",DateUtil.beginOfDay(new Date()));
    List<EpidemicWarning> warningList = epidemicWarningMapper.selectList(queryWrapper);

    //统计所有打卡
    QueryWrapper<UserGate> gateQueryWrapper = new QueryWrapper<>();
    gateQueryWrapper.ge("time_",DateUtil.beginOfDay(new Date()))
        .le("time_",DateUtil.endOfDay(new Date()));
    List<UserGate> userGates = userGateMapper.selectList(gateQueryWrapper);
    List<EpidemicDTO> list = new ArrayList<>();
    iPage.getRecords().forEach(l->{
      EpidemicDTO epidemicDTO = new EpidemicDTO();
      epidemicDTO.setName(l.getPlatformProjectName());

      //今天测温人员
      List<UserGate> gates = userGates.stream().filter(u -> l.getId().equals(u.getTenantId()))
          .collect(Collectors.toList());

      //绿码红码黄码数据
      long green = gates.stream().filter(g -> Integer.valueOf(1).equals(g.getHealthCode())).count();
      long yellow = gates.stream().filter(g -> Integer.valueOf(2).equals(g.getHealthCode())).count();
      long red = gates.stream().filter(g -> Integer.valueOf(4).equals(g.getHealthCode())).count();
      epidemicDTO.setGreen((int)green);
      epidemicDTO.setYellow((int)yellow);
      epidemicDTO.setRed((int)red);

      //体温数据
      Set<String> set1 = warningList.stream().filter(w -> !Integer.valueOf(2).equals(w.getType())
          && l.getId().equals(w.getTenantId())).map(w -> w.getUserId()).collect(Collectors.toSet());
      epidemicDTO.setTemperatureError(set1.size());
      epidemicDTO.setTemperatureSuc(gates.size()-set1.size());

      //健康码数据
      Set<String> set2 = warningList.stream().filter(w -> !Integer.valueOf(1).equals(w.getType())
          && l.getId().equals(w.getTenantId())).map(w -> w.getUserId()).collect(Collectors.toSet());
      epidemicDTO.setHealthError(set2.size());
      epidemicDTO.setHealthSuc(gates.size()-set2.size());

      list.add(epidemicDTO);
    });
    newIPage.setRecords(list);
    return newIPage;
  }

  /**
   * 当前现场人员统计总人数
   */
  @Override
  public LobarUserDTO countAll(UserProjectDTO userProjectDTO) {
    LobarUserDTO lobarUserDTO = new LobarUserDTO();
    DateTime dateTime = DateUtil.beginOfDay(new Date());
    //当天考勤情况
    List<UserRecord> userRecords = userRecordMapper.countAllByEnterprise(userProjectDTO);
    if (userProjectDTO.getStartTime().equals(dateTime)){
      //当天
      //统计在岗总人数
      List<UserProject> projectList = userProjectMapper.countAllByEnterprise(userProjectDTO);
      lobarUserDTO.setIn(projectList.size());
    }else {
      lobarUserDTO.setIn(userRecords.size());
    }

    List<String> list = userRecords.stream().filter(u->!Integer.valueOf(0).equals(u.getRecordType()))
        .map(u -> u.getUserId()).collect(Collectors.toList());
    lobarUserDTO.setAttendance(list.size());
    //统计出勤率
    lobarUserDTO.setPart(PercentageUtils.computePercentTwo(lobarUserDTO.getAttendance(),lobarUserDTO.getIn()));
    return lobarUserDTO;
  }

  /**
   * 折线图(项目级)
   */
  @Override
  public List<LobarUserDTO> countByProject(UserProjectDTO userProjectDTO) {
    //判断按月还是按日
    if (Integer.valueOf(1).equals(userProjectDTO.getFindType())){
      //按月
      String startMonthStr = userProjectDTO.getStartMonthStr();
      String endMonthStr = userProjectDTO.getEndMonthStr();
      String[] split = endMonthStr.split("-");
      Date starTime = DateUtil.beginOfMonth(DateUtil.parseDate(startMonthStr + "-01"));
      int lengthOfMonth = DateUtil
          .lengthOfMonth(Integer.valueOf(split[1]), DateUtil.isLeapYear(Integer.valueOf(split[0])));
      Date endTime = DateUtil.endOfMonth(DateUtil.parseDate(endMonthStr+"-"+lengthOfMonth));
      userProjectDTO.setStartTime(starTime);
      userProjectDTO.setEndTime(endTime);
    }
    //开始时间
    userProjectDTO.setStartTime(DateUtil.beginOfDay(userProjectDTO.getStartTime()));
    //结束时间
    userProjectDTO.setEndTime(DateUtil.endOfDay(userProjectDTO.getEndTime()));
    List<UserRecordDTO> userRecordDTOList = userRecordMapper.countByProject(userProjectDTO);
    String format = "yyyy-MM-dd";
    //分类
    if (Integer.valueOf(1).equals(userProjectDTO.getFindType())) {
      //按月
      format = "yyyy-MM";
    }
    String finalFormat = format;
    Map<String, List<UserRecordDTO>> listMap = userRecordDTOList.stream().collect(Collectors.groupingBy(c -> DateUtil.format(c.getRecordTime(),
        finalFormat)));
    //统计
    //组织时间段数据
    List<LobarUserDTO> lobarUserDTOS = getList(userProjectDTO,format);;
    List<LobarUserDTO> newList = new ArrayList<>();
    listMap.forEach((k,v) ->{
      LobarUserDTO lobarUserDTO = new LobarUserDTO();
      lobarUserDTO.setIn(v.size());
      long count = v.stream().filter(va -> !Integer.valueOf(0).equals(va.getRecordType())).count();
      lobarUserDTO.setAttendance((int)count);
      lobarUserDTO.setName(k);
      newList.add(lobarUserDTO);
    });
    lobarUserDTOS.forEach(l->{
      List<LobarUserDTO> dtos = newList.stream().filter(n -> n.getName().equals(l.getName()))
          .collect(Collectors.toList());
      if (dtos.size() > 0){
        LobarUserDTO userDTO = dtos.get(0);
        l.setAttendance(userDTO.getAttendance());
        //分类
        if (Integer.valueOf(1).equals(userProjectDTO.getFindType())) {
          l.setIn(userDTO.getIn()+l.getIn());
        }else if (l.getIn()==0){
          l.setIn(userDTO.getIn()+l.getIn());
        }
      }
    });
    return lobarUserDTOS;
  }

  /**
   * 工种统计（企业级）
   */
  @Override
  public Map<String, List<LobarScreenDTO>> countEnWorkType(String tenantId) {
    Map<String, List<LobarScreenDTO>> map = new HashMap<>();
    //查询当天所有的考勤记录
    String workTypeName = "作业人员";
    List<UserProject> userProjects = userRecordMapper.countEnWorkTypeToDay(tenantId);
    //过滤非管理人员
    List<UserProject> otherUserProjects = userProjects.stream()
        .filter(u -> StringUtils.isNotBlank(u.getWorkType()) && !u.getWorkType().startsWith("管理人员"))
        .collect(Collectors.toList());
    //第三级再分组
    List<LobarScreenDTO> otherlobarScreenDTOS = new ArrayList<>();
    Map<String, List<UserProject>> otherSonMap = otherUserProjects.stream().filter(u->StringUtils.isNotBlank(u.getWorkType()))
        .collect(Collectors.groupingBy(c -> c.getWorkType()
            .substring(c.getWorkType().lastIndexOf("/") + 1)));
    otherSonMap.forEach((key,value) ->{
      LobarScreenDTO lobarScreenDTO = new LobarScreenDTO();
      lobarScreenDTO.setName(key);
      //出勤人数
      long count = value.stream().filter(v -> StringUtils.isNotBlank(v.getId())).count();
      lobarScreenDTO.setNum((int)count);
      lobarScreenDTO.setIn(value.size());
      lobarScreenDTO.setPart(PercentageUtils.computePercentTwo((int)count,value.size()));
      otherlobarScreenDTOS.add(lobarScreenDTO);
    });
    otherlobarScreenDTOS.sort(getLobarScreenDTOComparator());
    map.put("工种",otherlobarScreenDTOS);


    //过滤作业人员
    List<UserProject> zyUserProjects = userProjects.stream().filter(
        u -> StringUtils.isNotBlank(u.getWorkType()) && u.getWorkType().startsWith(workTypeName))
        .collect(Collectors.toList());
    //分类
    Map<String, List<UserProject>> listMap = zyUserProjects.stream().filter(u->StringUtils.isNotBlank(u.getWorkType())).collect(Collectors.groupingBy(
        u -> u.getWorkType()
            .substring(u.getWorkType().indexOf("/") + 1, u.getWorkType().lastIndexOf("/"))));
    listMap.forEach((k,v)->{
      List<LobarScreenDTO> lobarScreenDTOS = new ArrayList<>();
      //第三级再分组
      Map<String, List<UserProject>> sonMap = v.stream().filter(u->StringUtils.isNotBlank(u.getWorkType()))
          .collect(Collectors.groupingBy(c -> c.getWorkType()
              .substring(c.getWorkType().lastIndexOf("/") + 1)));
      sonMap.forEach((key,value) ->{
        LobarScreenDTO lobarScreenDTO = new LobarScreenDTO();
        lobarScreenDTO.setName(key);
        //出勤人数
        long count = value.stream().filter(va -> StringUtils.isNotBlank(va.getId())).count();
        lobarScreenDTO.setNum((int)count);
        lobarScreenDTO.setIn(value.size());
        lobarScreenDTO.setPart(PercentageUtils.computePercentTwo((int)count,value.size()));
        lobarScreenDTOS.add(lobarScreenDTO);
      });
      lobarScreenDTOS.sort(getLobarScreenDTOComparator());
      map.put(k,lobarScreenDTOS);
    });
    return map;
  }

  /**
   * 在场情况
   */
  @Override
  public Map<String, Integer> onArea() {
    List<Integer> list = new ArrayList<>();
    list.add(1);list.add(2);list.add(3);
    QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("delete_state_",1)
        .eq("status_",1)
        .in("on_area_",list);
    List<UserProject> userProjects = userProjectMapper.selectList(queryWrapper);
    //施工区
    long count1 = userProjects.stream().filter(u -> Integer.valueOf(1).equals(u.getOnArea()))
        .count();
    //办公区
    long count2 = userProjects.stream().filter(u -> Integer.valueOf(2).equals(u.getOnArea()))
        .count();
    //生活区
    long count3 = userProjects.stream().filter(u -> Integer.valueOf(3).equals(u.getOnArea()))
        .count();
    Map<String, Integer> map = new HashMap<>();
    map.put("1",(int)count1);
    map.put("2",(int)count2);
    map.put("3",(int)count3);
    return map;
  }

  /**
   * 面板机最近打卡计数和最近打卡人数
   */
  @Override
  public Map<String, Object> getByDeviceCode(String deviceCode) {
    Map<String, Object> map = new HashMap<>();
    //查询今天的打卡次数
    Date date = new Date();
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    LambdaQueryWrapper<UserClock> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    lambdaQueryWrapper.eq(UserClock::getGateCode,deviceCode)
        .and(i -> i.ne(UserClock::getIsRecord, 0).or().isNull(UserClock::getIsRecord))
        .eq(UserClock::getTenantId,tenantId)
        .le(UserClock::getClockTime,DateUtil.endOfDay(date))
        .ge(UserClock::getClockTime,DateUtil.beginOfDay(date));
    Integer integer = userClockMapper.selectCount(lambdaQueryWrapper);
    map.put("num",integer);
    //最近10次打卡
    List<UserClockDTO> userClockDTOs = userClockMapper.getByDeviceCode(deviceCode,tenantId,10);
    map.put("list",userClockDTOs);
    return map;
  }

  /**
   * 岗亭大屏在场人数
   */
  @Override
  public Map<String, Integer> onNum4Box() {
    Map<String, Integer> map = new HashMap<>();
    List<LobarScreenDTO> lobarScreenDTOS = new ArrayList<>();
    LobarScreenDTO lobarScreenDTO1 = new LobarScreenDTO();
    lobarScreenDTO1.setName("施工区");
    LobarScreenDTO lobarScreenDTO2 = new LobarScreenDTO();
    lobarScreenDTO2.setName("办公区");
    LobarScreenDTO lobarScreenDTO3 = new LobarScreenDTO();
    lobarScreenDTO3.setName("生活区");
    lobarScreenDTOS.add(lobarScreenDTO1);lobarScreenDTOS.add(lobarScreenDTO2);
    lobarScreenDTOS.add(lobarScreenDTO3);
    //查询该项目属于哪种考勤在场判断
    String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    List<UserProjectDTO> userProjectList = userProjectMapper.getOnArea(tenantId,null);
    //过滤分包
    //1施工区
    long count1 = userProjectList.stream().filter(u -> Integer.valueOf(1).equals(u.getOnArea()))
        .count();
    //2办公区
    long count2 = userProjectList.stream().filter(u -> Integer.valueOf(2).equals(u.getOnArea()))
        .count();
    //3生活区
    long count3 = userProjectList.stream().filter(u -> Integer.valueOf(3).equals(u.getOnArea()))
        .count();
    lobarScreenDTOS.get(0).setNum((int)count1);
    lobarScreenDTOS.get(1).setNum((int)count2);
    lobarScreenDTOS.get(2).setNum((int)count3);
    lobarScreenDTOS.forEach(l->{
      map.put(l.getName(),l.getNum());
    });
    if(StringUtils.isBlank(tenantId)){
      tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
    }
    //在场总人数
    QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_",tenantId)
        .eq("status_",1);
    Integer integer = userProjectMapper.selectCount(queryWrapper);
    map.put("sum",integer);
    return map;
  }

  private Comparator<LobarScreenDTO> getLobarScreenDTOComparator() {
    return (a, b) -> {
      Double aPart = Double.valueOf(a.getPart().replaceAll("%", ""));
      Double bPart = Double.valueOf(b.getPart().replaceAll("%", ""));
      if (aPart > bPart) {
        return -1;
      } else if (aPart < bPart) {
        return 1;
      } else {
        int aNum = a.getNum();
        int bNum = b.getNum();
        if (aNum > bNum) {
          return -1;
        } else if (aNum < bNum) {
          return 1;
        } else {
          int aIn = a.getIn();
          int bIn = b.getIn();
          if (aIn > bIn) {
            return -1;
          } else {
            return 1;
          }
        }
      }
    };
  }

  //组织时间段数据
  private List<LobarUserDTO> getList(UserProjectDTO userProjectDTO,String format) {
    //判断时间是否包含当天。包含当天的话需要查询当天在场人数
    //今天时间格式化
    String today = DateUtil.format(new Date(), format);
    int toDayIn = 0;
    if (userProjectDTO.getEndTime().getTime() >= System.currentTimeMillis()){
      toDayIn =  userProjectMapper.countInToday(userProjectDTO);
    }
    List<LobarUserDTO> list = new ArrayList<>();
    Calendar cal = Calendar.getInstance();
    cal.setTime(userProjectDTO.getStartTime());
    Boolean flag = Integer.valueOf(1).equals(userProjectDTO.getFindType());
    int dayType = flag?Calendar.MONTH:Calendar.DATE;
    int mMum = (int)DateUtil.betweenMonth(userProjectDTO.getStartTime(), userProjectDTO.getEndTime(), true);
    int dNum = (int)DateUtil.betweenDay(userProjectDTO.getStartTime(), userProjectDTO.getEndTime(), true);
    int num = flag?mMum:dNum;
    for (int i = 0; i <= num; i++) {
      if (i>0){
        cal.add(dayType,1);
      }
      LobarUserDTO lobarUserDTO = new LobarUserDTO();
      lobarUserDTO.setName(DateUtil.format(cal.getTime(),format));
      if (today.equals(lobarUserDTO.getName())){
        lobarUserDTO.setIn(toDayIn);
      }
      list.add(lobarUserDTO);
    }
    return list;
  }

  /**
   * 实体转换
   * @param dtoList
   * @param r
   */
  private void toCover(List<UserProjectDTO> dtoList, EnterpriseDTO r) {
    //根据tenantId分组
    Map<String, List<UserProjectDTO>> listMap = dtoList.stream()
        .collect(Collectors.groupingBy(UserProjectDTO::getTenantId));
    List<LobarUserDTO> sonList = new ArrayList<>();
    listMap.forEach((k,v) ->{
      UserProjectDTO projectDTO = v.get(0);
      LobarUserDTO lobarUserDTO = new LobarUserDTO();
      lobarUserDTO.setName(projectDTO.getProjectName());
      long count = v.stream().filter(v1 -> StringUtils.isNotBlank(v1.getId())).count();
      lobarUserDTO.setIn((int)count);
      sonList.add(lobarUserDTO);
    });
    //人数排序
    List<LobarUserDTO> userDTOS = sonList.stream()
        .sorted(Comparator.comparing(LobarUserDTO::getIn).reversed()).collect(Collectors.toList());
    r.setSonList(userDTOS);
  }

  /**
   * 获取各个类别人数(项目部管理人员,其他管理人员,施工作业人员)
   * @param userRecords
   * @param projectUsers
   * @param l
   * @param lobarUserDTOS
   */
  private void getUses(List<UserRecord> userRecords, List<UserProjectDTO> projectUsers,List<UserProjectDTO> onProjectUsers,
      LinkappTenantDTO l, List<LobarUserDTO> lobarUserDTOS,String name) {
    LobarUserDTO lobarUserDTO = new LobarUserDTO();
    lobarUserDTO.setName(name);
    List<String> userIds = projectUsers.stream().filter(p -> l.getId().equals(p.getTenantId()))
        .map(p -> p.getUserId()).collect(Collectors.toList());
    List<String> onUserIds = onProjectUsers.stream().filter(p -> l.getId().equals(p.getTenantId()))
        .map(p -> p.getUserId()).collect(Collectors.toList());
    lobarUserDTO.setIn(userIds.size());
    int size = userRecords.stream()
        .filter(u -> l.getId().equals(u.getTenantId()) && userIds.contains(u.getUserId()))
        .map(p -> p.getUserId()).collect(Collectors.toList()).size();
    lobarUserDTO.setOn(onUserIds.size());
    lobarUserDTO.setIn(userIds.size());
    lobarUserDTO.setAttendance(size);
    lobarUserDTO.setPart(PercentageUtils.computePercentTwo(size,userIds.size()));
    lobarUserDTOS.add(lobarUserDTO);
  }

  private Set<String> getOnNum(String tenantId, Date startTime, Date endTime,
      Integer type, Boolean filter) {
    QueryWrapper<UserClock> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_",tenantId)
        .and(i -> i.ne("is_record_", 0).or().isNull("is_record_"))
        .eq("direction_",1)
        .ge("clock_time", startTime)
        .le("clock_time",endTime);
    if (null != type && filter){
      filterByType(tenantId, queryWrapper);
    }
    List<UserClock> clocks = userClockMapper.selectList(queryWrapper);
    return clocks.stream().map(c -> c.getUserId()).collect(Collectors.toSet());
  }

  private void filterByType(String tenantId, QueryWrapper queryWrapper) {
    //查询所有的符合条件的参建单位
    List<UserProjectDTO> userProjectDTOS = userProjectMapper.findByTenantId(tenantId);
    Config typeConfig = configService
        .getOneByKey("LABOUR_BIG_SCREEN_LABOUR_COMPANY_TYPE");
    if(typeConfig!=null){
      String value = typeConfig.getValue();
      if(StringUtils.isNotBlank(value)){
        JSONArray jsonArray = JSONUtil.parseArray(value);
        //过滤掉非专业单位和分包单位的
        userProjectDTOS.removeIf(u-> !jsonArray.contains(u.getBuildType()));
        List<String> userIds = userProjectDTOS.stream().map(item -> item.getUserId())
            .collect(Collectors.toList());
        queryWrapper.in("user_id_",userIds);
      }
    }
  }

  private List<String> getAttendance(String tenantId, Date startTime, Date endTime,
      Integer type, Boolean filter) {
    QueryWrapper<UserRecord> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("tenant_id_",tenantId)
        .ge("record_time_", startTime)
        .le("record_time_",endTime);
    if (null != type && filter){
      filterByType(tenantId, queryWrapper);
    }
    List<UserRecord> recordList = userRecordMapper.selectList(queryWrapper);
    List<String> records = recordList.stream()
        .filter(r -> !Integer.valueOf(0).equals(r.getRecordType())).map(r->r.getUserId())
        .collect(Collectors.toList());
    return records;
  }

  //总预警数
  private Integer sumWarning(WarningDTO warningDTO,String tenantId) {
    List<LobarScreenDTO> sumList = new ArrayList<>();
    QueryWrapper<UserWarning> userWrapper = new QueryWrapper<>();
    userWrapper.eq("tenant_id_",tenantId);
    Integer user = userWarningMapper.selectCount(userWrapper);
    LobarScreenDTO userDTO = new LobarScreenDTO();
    userDTO.setName("人员出勤预警");
    userDTO.setNum(user);
    sumList.add(userDTO);

    QueryWrapper<GroupWarning> groupWrapper = new QueryWrapper<>();
    groupWrapper.eq("tenant_id_",tenantId);
    Integer group = groupWarningMapper.selectCount(groupWrapper);
    LobarScreenDTO groupDTO = new LobarScreenDTO();
    groupDTO.setName("班组出勤预警");
    groupDTO.setNum(group);
    sumList.add(groupDTO);

    QueryWrapper<AgeWarning> ageWrapper = new QueryWrapper<>();
    ageWrapper.eq("tenant_id_",tenantId);
    Integer age = ageWarningMapper.selectCount(ageWrapper);
    LobarScreenDTO ageDTO = new LobarScreenDTO();
    ageDTO.setName("年龄预警");
    ageDTO.setNum(age);
    sumList.add(ageDTO);

    QueryWrapper<CertificateWarning> certificateWrapper = new QueryWrapper<>();
    certificateWrapper.eq("tenant_id_",tenantId);
    Integer certificate = certificateWarningMapper.selectCount(certificateWrapper);
    LobarScreenDTO certificateDTO = new LobarScreenDTO();
    certificateDTO.setName("证书预警");
    certificateDTO.setNum(certificate);
    sumList.add(certificateDTO);

    //20221021 需求1005345 【WEB/劳务管理】人员出场异常预警变更去掉昨日、本月，增加今日
    QueryWrapper<UserOutinWarning> outinWrapper = new QueryWrapper<>();
    outinWrapper.eq("tenant_id_",tenantId);
    Integer outin = userOutinWarningMapper.selectCount(outinWrapper);
    LobarScreenDTO outinDTO = new LobarScreenDTO();
    outinDTO.setName("人员出场异常预警");
    outinDTO.setNum(outin);
    sumList.add(outinDTO);

    //降序排序
    List<LobarScreenDTO> dtoList = sumList.stream()
        .sorted(Comparator.comparing(LobarScreenDTO::getNum).reversed())
        .collect(Collectors.toList());
    warningDTO.setCompanyHours(dtoList);

    return user + group + age + certificate + outin;
  }

  //本月预警数
  private Integer monthWarning(String tenantId) {
    QueryWrapper<UserWarning> userWrapper = new QueryWrapper<>();
    userWrapper.eq("tenant_id_",tenantId);
    QueryWrapper<GroupWarning> groupWrapper = new QueryWrapper<>();
    groupWrapper.eq("tenant_id_",tenantId);
    QueryWrapper<AgeWarning> ageWrapper = new QueryWrapper<>();
    ageWrapper.eq("tenant_id_",tenantId);
    QueryWrapper<CertificateWarning> certificateWrapper = new QueryWrapper<>();
    certificateWrapper.eq("tenant_id_",tenantId);
    //筛选掉其他类型的参建公司
    Config typeConfig = configService
        .getOneByKey("LABOUR_BIG_SCREEN_LABOUR_COMPANY_TYPE");
    if(typeConfig!=null){
      String value = typeConfig.getValue();
      if(StringUtils.isNotBlank(value)){
        JSONArray jsonArray = JSONUtil.parseArray(value);
        List<UserProjectDTO> userProjectDTOS = userProjectMapper.findByTenantId(tenantId);
        //过滤掉非专业单位和分包单位的
        userProjectDTOS.removeIf(u-> !jsonArray.contains(u.getBuildType()));
        List<String> userIds = userProjectDTOS.stream().map(item -> item.getUserId())
            .collect(Collectors.toList());
        userWrapper.in("user_id_",userIds);
        //查询所有符合条件的公司id
        QueryWrapper<LaborCompany> laborCompanyWrapper = new QueryWrapper<>();
        laborCompanyWrapper.in("build_type_",jsonArray);
        List<LaborCompany> laborCompanies = laborCompanyService.getBaseMapper()
            .selectList(laborCompanyWrapper);
        List<String> companyIds = laborCompanies.stream().map(item -> item.getId())
            .collect(Collectors.toList());
        //找到所有的companyProjectId
        QueryWrapper<LaborCompanyProject> laborCompanyProjectWrapper = new QueryWrapper<>();
        laborCompanyProjectWrapper.eq("tenant_id_",tenantId);
        laborCompanyProjectWrapper.in("company_id_",companyIds);
        List<LaborCompanyProject> laborCompanyProjects = laborCompanyProjectMapper
            .selectList(laborCompanyProjectWrapper);
        List<String> companyProjectIds = laborCompanyProjects.stream().map(item -> item.getId())
            .collect(Collectors.toList());
        QueryWrapper<Group> groupaWrapper = new QueryWrapper<>();
        groupaWrapper.eq("tenant_id_",tenantId);
        groupaWrapper.in("company_project_id_",companyProjectIds);
        List<Group> groups = groupMapper.selectList(groupaWrapper);
        List<String> groupIds = groups.stream().map(item -> item.getId())
            .collect(Collectors.toList());
        groupWrapper.in("group_id_",groupIds);
        ageWrapper.in("user_id_",userIds);
        certificateWrapper.in("user_id_",userIds);
      }
    }
    Integer user = userWarningMapper.selectCount(userWrapper);
    Integer group = groupWarningMapper.selectCount(groupWrapper);
    Integer age = ageWarningMapper.selectCount(ageWrapper);
    Integer certificate = certificateWarningMapper.selectCount(certificateWrapper);
    return user+group+age+certificate;
  }

  /**
   * 昨天预警数
   * @param tenantId
   */
  private Integer yesterdayWarning(String tenantId) {
    QueryWrapper<UserWarning> userWrapper = new QueryWrapper<>();
    userWrapper.eq("tenant_id_",tenantId)
        .ge("warning_time_", DateUtil.beginOfDay(DateUtil.yesterday()))
        .le("warning_time_",DateUtil.endOfDay(DateUtil.yesterday()));
    Integer user = userWarningMapper.selectCount(userWrapper);

    QueryWrapper<GroupWarning> groupWrapper = new QueryWrapper<>();
    groupWrapper.eq("tenant_id_",tenantId)
        .ge("warning_time_",DateUtil.beginOfDay(DateUtil.yesterday()))
        .le("warning_time_",DateUtil.endOfDay(DateUtil.yesterday()));
    Integer group = groupWarningMapper.selectCount(groupWrapper);

    QueryWrapper<AgeWarning> ageWrapper = new QueryWrapper<>();
    ageWrapper.eq("tenant_id_",tenantId)
        .ge("warning_time_",DateUtil.beginOfDay(DateUtil.yesterday()))
        .le("warning_time_",DateUtil.endOfDay(DateUtil.yesterday()));
    Integer age = ageWarningMapper.selectCount(ageWrapper);

    QueryWrapper<CertificateWarning> certificateWrapper = new QueryWrapper<>();
    certificateWrapper.eq("tenant_id_",tenantId)
        .ge("warning_time_",DateUtil.beginOfDay(DateUtil.yesterday()))
        .le("warning_time_",DateUtil.endOfDay(DateUtil.yesterday()));
    Integer certificate = certificateWarningMapper.selectCount(certificateWrapper);

    //20221021 需求1005345 【WEB/劳务管理】人员出场异常预警
    QueryWrapper<UserOutinWarning> outinQueryWrapper = new QueryWrapper<>();
    outinQueryWrapper.eq("tenant_id_",tenantId)
            .ge("warning_time_",DateUtil.beginOfDay(DateUtil.yesterday()))
            .le("warning_time_",DateUtil.endOfDay(DateUtil.yesterday()));
    Integer outin = userOutinWarningMapper.selectCount(outinQueryWrapper);

    return user + group + age + certificate + outin;
  }

  /**
   * 查询劳务配置是否需要过滤分包单位
   */
  private Boolean isFilter(String tenantId){
    LobarSet lobarSet = lobarSetService.getByTenantId(tenantId);
    return Integer.valueOf(2).equals(lobarSet.getAllType());
  }

  /**
   * 获取籍贯
   * @param card
   * @return
   */
  private String getNative(String card) {
    String cardNo;
    try {
      cardNo = card.substring(0, 2);
    } catch (Exception e) {
      return "未知";
    }
    if (null == nativeMap){
      nativeMap = new HashMap<>();
      nativeMap.put("11","北京");nativeMap.put("12","天津");nativeMap.put("13","河北");nativeMap.put("14","山西");
      nativeMap.put("15","内蒙古");nativeMap.put("21","辽宁");nativeMap.put("22","吉林");nativeMap.put("23","黑龙江");
      nativeMap.put("31","上海");nativeMap.put("32","江苏");nativeMap.put("33","浙江");nativeMap.put("34","安徽");
      nativeMap.put("35","福建");nativeMap.put("36","江西");nativeMap.put("37","山东");nativeMap.put("41","河南");
      nativeMap.put("42","湖北");nativeMap.put("43","湖南");nativeMap.put("44","广东");nativeMap.put("45","广西");
      nativeMap.put("46","海南");nativeMap.put("50","重庆");nativeMap.put("51","四川");nativeMap.put("52","贵州");
      nativeMap.put("53","云南");nativeMap.put("54","西藏");nativeMap.put("61","陕西");nativeMap.put("62","甘肃");
      nativeMap.put("63","青海");nativeMap.put("64","宁夏");nativeMap.put("65","新疆");
    }
    return nativeMap.get(cardNo)==null?"未知":nativeMap.get(cardNo);
  }

  private Map<String, String> nativeMap;
}
